package com.m.job.server.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;

import com.client.job.core.model.*;
import com.m.job.logs.service.MJobRunLogsService;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.client.job.core.constant.JobInstanceStatus;
import com.client.job.utils.DataResult;
import com.client.job.utils.MJobUtils;
import com.m.job.compents.JobAndInstanceCompent;
import com.m.job.server.mapper.MJobInstanceMapper;
import com.m.job.server.mapper.MJobMapper;
import com.m.job.server.model.MJobInstanceDto;
import com.m.job.server.service.MJobRegisterService;
import com.m.utils.IdUtil;

import javax.annotation.Resource;

@Service
@Transactional
public class MJobRegisterServiceImpl implements MJobRegisterService {

	@Resource
	private MJobMapper jobMapper;

	@Resource
	private MJobInstanceMapper mJobInstanceMapper;

	@Resource
	private JobAndInstanceCompent jobInstanceCompent;

	@Resource
	private MJobRunLogsService  mJobRunLogsService;

	@SuppressWarnings("unchecked")
	@Override
	public void dealClientDataJSon(String dataJson) throws Exception {
		DataResult result = JSON.parseObject(dataJson, DataResult.class);
		if (result.getRequestType() == 0) {
			List<JSONObject> obJlist = (List<JSONObject>) result.getData();
			obJlist.forEach(o -> {
				try {
					registerJobAndInstance(JSON.toJavaObject(o, MJobVo.class));
				} catch (Exception e) {
					e.printStackTrace();
				}
			});
		}

		//操作日志推送
		if(result.getRequestType() == 1){
			JSONObject obj = (JSONObject) result.getData();
			insertLogs(JSON.toJavaObject(obj,MJobRunLogsVo.class));
		}
	}
	//插入
	private void  insertLogs(MJobRunLogsVo runLogsVo){
		mJobRunLogsService.insertMjobRunLog(runLogsVo);
	}

	/**
	 * 注册单个实例
	 * 
	 * @param jobVo
	 * @throws Exception
	 */
	private synchronized void registerJobAndInstance(MJobVo jobVo) throws Exception {
		// 查询当前Job以及Job实例
		MJob existJob = jobMapper.getByJobCode(jobVo.getMJob().getJobCode());
		MJobInstance existInstance = mJobInstanceMapper.getByServerInfoAndJobName(
				jobVo.getMJobInstanceList().get(0).getAppName(), jobVo.getMJobInstanceList().get(0).getPort(),
				jobVo.getMJob().getJobName());

		boolean jobNullFlag = existJob == null;
		boolean jobInstanceNullFlag = existInstance == null;
		// 新增Mjob以及实例
		if (jobNullFlag && jobInstanceNullFlag) {
			existJob = jobVo.getMJob();
			existJob.setAppCounts(1);
			existJob.setJobId(IdUtil.genId());
			jobMapper.insert(existJob);
			existInstance = jobVo.getMJobInstanceList().get(0);
			existInstance.setJobName(existJob.getJobName());
			existInstance.setJobId(existJob.getJobId());
			existInstance.setJobStatus(JobInstanceStatus.JOB_RUNNING.getStatus());
			existInstance.setServerStatus(JobInstanceStatus.SERVER_RUNNING.getStatus());
			existInstance.setSort(0);
			existInstance.setMachineId(IdUtil.genId());
			mJobInstanceMapper.insert(MJobInstanceDto.buildNewDto(existInstance));
		}

		// JOB存在，实例存在，且被不被运行
		if (!jobNullFlag && !jobInstanceNullFlag
				&& existInstance.getJobStatus() != JobInstanceStatus.JOB_RUNNING.getStatus()) {
			// 不进行任何操作
			existInstance.setServerStatus(JobInstanceStatus.SERVER_RUNNING.getStatus());
			mJobInstanceMapper.update(MJobInstanceDto.buildNewDto(existInstance));
			jobInstanceCompent.registerInstanceList(existJob, jobVo.getMJobInstanceList(), null, null);
			return;
		}

		// 所有的Job的实例
		List<MJobInstanceDto> runningList = mJobInstanceMapper.getListByJobCode(existJob.getJobCode(),
				JobInstanceStatus.JOB_RUNNING.getStatus(), JobInstanceStatus.SERVER_RUNNING.getStatus());

		// 修改Mjob，新增实例
		if (!jobNullFlag && jobInstanceNullFlag) {
			// 运行实例+1
			jobMapper.lessAppCounts(existJob.getJobId(), -1);
			existInstance = jobVo.getMJobInstanceList().get(0);
			existInstance.setJobName(existJob.getJobName());
			existInstance.setJobId(existJob.getJobId());
			existInstance.setJobStatus(JobInstanceStatus.JOB_RUNNING.getStatus());
			existInstance.setServerStatus(JobInstanceStatus.SERVER_RUNNING.getStatus());
			existInstance.setSort(runningList.size());
			existInstance.setMachineId(IdUtil.genId());
			runningList.add(MJobInstanceDto.buildNewDto(existInstance));
			mJobInstanceMapper.insert(MJobInstanceDto.buildNewDto(existInstance));
		}

		// 修改Mjob,修改实例
		if (!jobNullFlag && !jobInstanceNullFlag) {
			// 运行实例+1
			if (existInstance.getServerStatus() != JobInstanceStatus.SERVER_RUNNING.getStatus()
					&& existInstance.getJobStatus() == JobInstanceStatus.JOB_RUNNING.getStatus()) {
				jobMapper.lessAppCounts(existJob.getJobId(), -1);
			}
			existInstance.setServerStatus(JobInstanceStatus.SERVER_RUNNING.getStatus());
			existInstance.setSort(runningList.size());
			mJobInstanceMapper.update(MJobInstanceDto.buildNewDto(existInstance));
			runningList.add(MJobInstanceDto.buildNewDto(existInstance));
		}

		List<MJob> jobList = jobMapper.getList(null);

		// 发送Socket
		jobInstanceCompent.registerInstanceList(existJob, 
				jobVo.getMJobInstanceList(), 
				jobList,
				MJobInstanceDto.dtoListToPoList(runningList));
	}

	@Override
	public synchronized void serverDown(String serverFlag) throws Exception {
		// 查询出当前应用上所有运行的服务
		MJobInstance mJobInstance = new MJobInstance();
		mJobInstance.setAppName(MJobUtils.getServerName(serverFlag));
		mJobInstance.setPort(MJobUtils.getAppPort(serverFlag));
		mJobInstance.setServerStatus(JobInstanceStatus.SERVER_RUNNING.getStatus());
		List<MJobInstanceDto> localInstanceList = mJobInstanceMapper.getExctList(MJobInstanceDto.buildNewDto(mJobInstance));
		// 关停服务
		if (!localInstanceList.isEmpty()) {
			mJobInstanceMapper.updateJobStatusByIdList(
					localInstanceList.stream().map(MJobInstance::getMachineId).collect(Collectors.toList()), null,
					JobInstanceStatus.SERVER_STOP.getStatus());
		}
		List<MJobInstanceDto> filter = localInstanceList.stream()
				.filter(o -> o.getJobStatus() == JobInstanceStatus.JOB_RUNNING.getStatus())
				.collect(Collectors.toList());
		localInstanceList.clear();
		localInstanceList.addAll(filter);
		mJobInstanceMapper.delByAppNameAndPort(MJobUtils.getAppPort(serverFlag), MJobUtils.getServerName(serverFlag));
		if (localInstanceList == null || localInstanceList.isEmpty()) {
			jobInstanceCompent.serverDown(null, null, null);
			return;
		}
		// JOB实例减
		Map<String, List<MJobInstance>> jobIdMap = localInstanceList.stream()
				.collect(Collectors.groupingBy(MJobInstance::getJobId));
		for (Entry<String, List<MJobInstance>> e : jobIdMap.entrySet()) {
			jobMapper.lessAppCounts(e.getKey(), e.getValue().size());
		}
		// 停止该应用所有Job
		MJobInstance localIns = new MJobInstance();
		localIns.setAppName(MJobUtils.getServerName(serverFlag));
		localIns.setPort(MJobUtils.getAppPort(serverFlag));
		localIns.setSort(null);
		localIns.setServerStatus(JobInstanceStatus.SERVER_STOP.getStatus());
		mJobInstanceMapper.updateByServerPort(MJobInstanceDto.buildNewDto(localIns));

		// 根据JobIds查询该应用上其他运行Job
		List<MJobInstanceDto> runInstanceList = mJobInstanceMapper.getListByJobIds(new ArrayList<>(jobIdMap.keySet()),
				JobInstanceStatus.SERVER_RUNNING.getStatus(), JobInstanceStatus.JOB_RUNNING.getStatus());

		if (runInstanceList == null || runInstanceList.isEmpty()) {
			jobInstanceCompent.serverDown(null, null, null);
			return;
		}

		// 修改运行中的任务排序
		for (Entry<String, List<MJobInstanceDto>> e : runInstanceList.stream()
				.collect(Collectors.groupingBy(MJobInstance::getJobId)).entrySet()) {
			Integer newSort = 0;
			for (MJobInstanceDto mi : e.getValue()) {
				mi.setSort(newSort);
				mJobInstanceMapper.update(mi);
				newSort++;
			}
		}

		// 查询所有的Job
		List<MJob> mjobList = jobMapper.getListByIds(jobIdMap.keySet());
		jobInstanceCompent.serverDown( MJobInstanceDto.dtoListToPoList(localInstanceList), mjobList, MJobInstanceDto.dtoListToPoList(runInstanceList));
	}

	@Override
	public synchronized void reCleanSocket(Set<String> hashExistServerFlagList) throws Exception {
		//查询出所有运行的服务
		MJobInstance mJobInstance = new MJobInstance();
		mJobInstance.setJobStatus(JobInstanceStatus.JOB_RUNNING.getStatus());
		mJobInstance.setServerStatus(JobInstanceStatus.SERVER_RUNNING.getStatus());
		List<MJobInstanceDto> list = mJobInstanceMapper.getExctList(MJobInstanceDto.buildNewDto(mJobInstance));
		if (list == null || list.isEmpty()) {
			// 无运行任务
			return;
		}
		
		List<String> allServer = list.stream().map(MJobInstanceDto::getServerInfo).collect(Collectors.toList());
		for(String server : allServer) {
			if(!hashExistServerFlagList.contains(server)) {
				serverDown(server);
			}
		}
		

		
	}

}
